home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / BTNGO.ZIP / BTNGOC.ZIP / ITEMDATA.CPP < prev    next >
C/C++ Source or Header  |  1993-09-28  |  19KB  |  519 lines

  1. #include<windows.h>
  2. #include<ctype.h>
  3. #include"wstring.hpp"
  4. #include"itemdata.hpp"
  5.  
  6. #ifdef DEBUG_SCREENS
  7. extern WinMessageString screen;
  8. #endif
  9. extern WinMessageString errscreen;
  10. extern unsigned int winver;
  11.  
  12. /////////////////////////////////////
  13. // defines
  14. #define CFP(x) (&((char __far *)memptr)[x]) // create char __far * x bytes into buffer
  15. #define CFP2(x) (&((char __far *)memptr2)[x]) // create char __far * x bytes into buffer
  16.  
  17. /////////////////////////////////////
  18. // local data types
  19.  
  20. struct GroupInfo{
  21.     WORD name;
  22.     WORD executable;
  23.     WORD executable_with_path;
  24.     WORD parameters;
  25.     WORD default_directory;
  26.     WORD minimized;
  27. };
  28. struct GroupFileHeader{
  29.     char cIdentifier[4];
  30.     WORD wCheckSum;
  31.     WORD cbGroup;
  32.     WORD nCmdShow;
  33.     RECT rcNormal;
  34.     POINT ptMin;
  35.     WORD pName;
  36.     WORD wLogPixelsX;
  37.     WORD wLogPixelsY;
  38.     BYTE bBitsPerPixel;
  39.     BYTE bPlanes;
  40.     WORD wReserved;
  41.     WORD cItems;
  42. };
  43. struct ItemData{
  44.     POINT pt;
  45.     WORD iIcon; // 0 if normal, 1 if minimized
  46.     WORD cbResource;
  47.     WORD cbANDPlane;
  48.     WORD cbXORPlane;
  49.     WORD pHeader;
  50.     WORD pANDPlane;
  51.     WORD pXORPlane;
  52.     WORD pName;
  53.     WORD pCommand;
  54.     WORD pIconPath; // 0 or ptr to initial path
  55. };
  56. struct TagData{
  57.     WORD wID;
  58.     WORD wItem;
  59.     WORD cb;
  60.     union{
  61.         char cnext[1];
  62.         int inext;
  63.     }next;
  64. };
  65. struct IconHeader{ // pointed to by ItemData.pHeader
  66.     int xHotSpot;
  67.     int yHotSpot;
  68.     int cx; // icon width
  69.     int cy; // icon height
  70.     int cbWidth; // bytes per row including WORD alignment
  71.     BYTE bPlanes; // nbr planes
  72.     BYTE bBitsPixel; // bits per pixel
  73. };
  74. /////////////////////////////////////
  75. // GroupFile member functions
  76.  
  77. GroupFile::GroupFile(char *p){
  78.     opened=0;
  79.     items_to_read=0;
  80.     tag_bytes=0;
  81.     memhandle=NULL;
  82.     memptr=NULL;
  83.     memhandle2=NULL;
  84.     memptr2=NULL;
  85.     got_icon_default_data=0;
  86.     set_filename(p);
  87. }
  88. GroupFile::~GroupFile(){
  89.     if(opened)_lclose(hf);
  90.     if(memhandle!=NULL){
  91.         if(memptr!=NULL)GlobalUnlock(memhandle);
  92.         GlobalFree(memhandle);
  93.     }
  94.     if(memhandle2!=NULL){
  95.         if(memptr2!=NULL)GlobalUnlock(memhandle2);
  96.         GlobalFree(memhandle2);
  97.     }
  98.     #ifdef DEBUG_SCREENS
  99.     screen<<grpfil<<" destructed\n";
  100.     screen.show();
  101.     #endif
  102. }
  103. void GroupFile::set_filename(char *p){
  104.     error_condition_exists=(NULL==(grpfil=p))?1:0;
  105. }
  106. int GroupFile::openfile(){
  107.     if(error())return 0;
  108.     // assume failure so can just return
  109.     error_condition_exists=1;
  110.     if(opened)return 0;
  111.     opened=((hf=_lopen(grpfil,READ))==HFILE_ERROR)?0:1;
  112.     if(!opened)return 0;
  113.     filebytes=_llseek(hf,0,2); // go to end of file
  114.     if(filebytes==HFILE_ERROR||_llseek(hf,0,0)==HFILE_ERROR)return 0; // go to beginning
  115.     if(filebytes>60000L){
  116.         errscreen<<"Group file is too large. Aborting.\n";
  117.         return 0;
  118.     }
  119.     if(filebytes<(sizeof(GroupFileHeader)+2+sizeof(ItemData)+sizeof(IconHeader))){
  120.         errscreen<<"Group file is empty or too small. Aborting.\n";
  121.         return 0;
  122.     }
  123.     if(NULL==(memhandle=GlobalAlloc(GMEM_FIXED,filebytes))){
  124.         errscreen<<"Could not allocate memory\n";
  125.         return 0;
  126.     }
  127.     if(NULL==(memptr=GlobalLock(memhandle))){
  128.         errscreen<<"Could not lock memory\n";
  129.         return 0;
  130.     }
  131.     if(_lread(hf,memptr,(UINT)filebytes)!=(UINT)filebytes){
  132.         errscreen<<"Could not read group file. Aborting.\n";
  133.         return 0;
  134.     }
  135.     GroupFileHeader __far *p=(GroupFileHeader __far *)memptr;
  136.     if(p->cIdentifier[0]!='P'||p->cIdentifier[1]!='M'||
  137.     p->cIdentifier[2]!='C'||p->cIdentifier[3]!='C'){
  138.         errscreen<<"Group file corrupted. Aborting.\n";
  139.         return 0;
  140.     }
  141.     pItemOffset=(int __far *)&p[1];
  142.     {
  143.         int ok=0;
  144.         for(;;){
  145.             WORD x;
  146.             if(p->cItems<1)break;
  147.             for(x=0;x<p->cItems;x++){
  148.                 if(pItemOffset[x]!=0){
  149.                     ok=1;
  150.                     break;
  151.                 }
  152.             }
  153.             break;
  154.         }
  155.         if(!ok){
  156.             errscreen<<"Group file is empty. Aborting.";
  157.             return 0;
  158.         }
  159.     }
  160.     _lclose(hf);
  161.     opened=0;
  162.     error_condition_exists=0;
  163.     return 1;
  164. }
  165. void GroupFile::readheader(){
  166.     if(error())return;
  167.     GroupFileHeader _far *p=(GroupFileHeader __far *)memptr;
  168.     // pItemOffset=(int *)&((GroupFileHeader *)memptr)[1];
  169.     items_to_read=p->cItems;
  170.     #ifdef DEBUG_SCREENS
  171.     screen<<"Group name is "<<CFP(p->pName)<<"\n";
  172.     #endif
  173.     // now, if in Win 3.1, associate tag data with items
  174.     // this is because the wItem part of TagData will become
  175.     // invalid (we'll need to sort the icons by position)
  176.     // so we'll use this convention:
  177.     //    ItemData  == TagData wID   usage
  178.     //    --------     -----------  -----------------------------
  179.     //     iIcon        0x8103       0 if normal, 1 if minimized
  180.     //     pIconPath    0x8101       0 or ptr to initial path
  181.     //
  182.     // pseudocode:
  183.     //      set all iIcons to 0, pIconPaths to 0
  184.     //      if in Windows 3.1 TagData may be present so
  185.     //          for each TagData entry
  186.     //              apply data to ItemData entry
  187.     //          end for
  188.     //      end if
  189.     {
  190.         int t;
  191.         ItemData __far *p;
  192.         for(t=0;t<items_to_read;t++){
  193.             if(pItemOffset[t]==0)continue;
  194.             p=(ItemData __far *)CFP(pItemOffset[t]);
  195.             p->iIcon=0;
  196.             p->pIconPath=0;
  197.         }
  198.     }
  199.     if(winver>=0x30A){
  200.         int keep_going=0;
  201.         GroupFileHeader __far *p=(GroupFileHeader __far *)memptr;
  202.         ItemData __far *q;
  203.         TagData __far *tdp;
  204.         if(filebytes>=(LONG)(p->cbGroup+6)){ // '6' sted sizeof(TagData) - sizeof(union)
  205.             tdp=(TagData __far *)CFP(p->cbGroup);
  206.             keep_going=1;
  207.         }
  208.         while(keep_going){
  209.             switch(tdp->wID){
  210.             case 0xFFFF: keep_going=0; break;
  211.             case 0x8101: // path in next.cnext
  212.                 q=(ItemData __far *)CFP(pItemOffset[tdp->wItem]);
  213.                 q->pIconPath=(WORD)(tdp->next.cnext-(char __far *)memptr);
  214.                 break;
  215.             case 0x8103: // app should be minimized
  216.                 q=(ItemData __far *)CFP(pItemOffset[tdp->wItem]);
  217.                 q->iIcon=1;
  218.                 break;
  219.             }
  220.             // '6' in next line is sizeof(TagData) - sizeof(union)
  221.             if((LONG)(((char __far *)tdp-(char __far *)memptr)+tdp->cb+6)>filebytes){
  222.                 keep_going=0;
  223.                 continue;
  224.             }
  225.             tdp=(TagData __far *)(((char __far *)tdp)+tdp->cb);
  226.         }
  227.     }
  228.     // ok now we can sort the item data by the icon's position
  229.     // so the group looks like it ought to
  230.     // use old'n'lame selection sort but it's good enough here...
  231.     if(items_to_read>1){
  232.         int min,x,left=items_to_read;
  233.         unsigned int temp;
  234.         unsigned int __far *p=(unsigned int __far *)pItemOffset;
  235.         while(left-->1){
  236.             for(x=0,min=0;x<=left;x++)if(second_lower(p[min],p[x]))min=x;
  237.             if(min!=0){temp=p[min];p[min]=*p;*p=temp;}
  238.             p++;
  239.         }
  240.     }
  241.     // now create the compacted version of the file
  242.     // first accumulate target size, then allocate space, then copy space
  243.     unsigned long size=0;
  244.     {
  245.         int left=items_to_read,found_items=0;
  246.         unsigned int __far *p=(unsigned int __far *)pItemOffset;
  247.         ItemData __far *i;
  248.         while(left&&*p){
  249.             i=(ItemData __far *)CFP(*p);
  250.             size+=sizeof(GroupInfo); // space for array entry
  251.             if(i->pName)size+=1+lstrlen(CFP(i->pName)); // space for entry's displayed name
  252.             if(i->pCommand)size+=1+lstrlen(CFP(i->pCommand)); // space for command line
  253.             if(i->pIconPath)size+=1+lstrlen(CFP(i->pIconPath)); // space for command path
  254.             p++;
  255.             left--;
  256.             found_items++;
  257.         }
  258.         items_to_read=found_items; // 'forget' about NULL entries
  259.     }
  260.     // no